package com.example.testdemo.spring.scan;

import android.content.Context;

import com.example.testdemo.annotation.Component;
import com.example.testdemo.spring.bean.BeanDefinition;
import com.example.testdemo.spring.bean.GenericBeanDefinition;
import com.example.testdemo.spring.factory.DefaultBeanFactory;
import com.example.testdemo.utils.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import dalvik.system.DexFile;

/**
 * <p>
 *
 * </p>
 *
 * @author 永健
 * @since 2020-03-29 01:01
 */
public abstract class ClassPathBeanDefinitionScanner implements BeanScanner {

    private DefaultBeanFactory beanFactory;

    public ClassPathBeanDefinitionScanner(DefaultBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    /**
     * 实现了我们的扫描接口的方法
     * @param context
     * @param packages
     * @return
     */
    @Override
    public List<BeanDefinition> scan(Context context, String packages) {
        List<String> className = getClassName(context, packages);
        List<BeanDefinition> beanDefinitions = new ArrayList<>();

        for (String clazz : className) {
            try {
                Class<?> aClass = Class.forName(clazz);
                Component component = aClass.getAnnotation(Component.class);
                if (StringUtils.isNull(component)) {
                    continue;
                }
                GenericBeanDefinition beanDefinition = new GenericBeanDefinition();

                String name = component.name();
                if (StringUtils.isBlank(name)) {
                    name = toLowerCaseFirstOne(aClass.getSimpleName());
                }
                beanDefinition.setBeanName(name);
                beanDefinition.setAliasName(name);
                beanDefinition.setBeanClass(aClass);
                beanDefinitions.add(beanDefinition);

                beanFactory.registerSingleton(name, beanDefinition);

            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return beanDefinitions;
    }

    /**
     * 筛选处指定包下的类
     * @param context
     * @param packageName
     * @return
     */
    private List<String> getClassName(Context context, String packageName) {
        List<String> classNameList = new ArrayList<String>();
        try {

            //通过DexFile查找当前的APK中可执行文件
            DexFile df = new DexFile(context.getPackageCodePath());

            //获取df中的元素  这里包含了所有可执行的类名 该类名包含了包名+类名的方式
            Enumeration<String> enumeration = df.entries();
            while (enumeration.hasMoreElements()) {
                String className = enumeration.nextElement();

                //在当前所有可执行的类里面查找包含有该包名的所有类
                if (className.contains(packageName)) {
                    classNameList.add(className);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return classNameList;
    }

    /**
     * 首字母小写
     * @param s
     * @return
     */
    private static String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0))) {
            return s;
        } else {
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
        }
    }
}
